using UnityEngine;
using System.Collections.Generic;
using System.Collections;
using Newtonsoft.Json;
using System.IO;
using System.Net;
//using EvonyExtension;
//using Frankfort.Threading.Internal;
using System.Threading;
//using Newtonsoft.Json;


public class LoadHttpResourceTask
{
    public enum ResourceType
    {
        texture,
        audioclip,
    }
    
    static string dirName = "network_resource";
    static HashSet<string> urlFileMap = null;

    public readonly string url;
    string filePath;
    public HashSet<System.Action<string, Object>> callBacks = new HashSet<System.Action<string, Object>>();
    Coroutine coroutine;
    WWW www;
    ResourceType resType;

    public LoadHttpResourceTask(string url, ResourceType resType)
    {
        this.url = url;
        this.resType = resType;
        string fileName = CommonUtil.md5(url);
        filePath = CommonUtil.cachePath + "/" + dirName + "/" + fileName;
    }

    public void Cancel()
    {
        HttpDownloadManager.instance.Cancel(url, HttpDownloadHandler);

        if (coroutine != null)
        {
            MyEventObject.instance.StopCoroutine(coroutine);
            coroutine = null;
        }

        if (www != null)
        {
            www.Dispose();
            www = null;
        }
    }

    public void Load()
    {
        if (urlFileMap == null)
        {
            urlFileMap = new HashSet<string>();
            string dirPath = CommonUtil.cachePath + "/" + dirName;
            if (System.IO.Directory.Exists(dirPath))
            {
                string[] filePaths = System.IO.Directory.GetFiles(dirPath, "*", SearchOption.TopDirectoryOnly);
                for (int i = 0; i < filePaths.Length; i++)
                {
                    string filePath = filePaths[i];
                    urlFileMap.Add(filePath);
                }
            }
            else
            {
                CommonUtil.CreateDir(dirPath);
            }
        }

        if (urlFileMap.Contains(filePath))
        {
            coroutine = MyEventObject.instance.StartCoroutine(LoadLocalCoroutine());
        }
        else
        {
            HttpDownloadManager.instance.Download(url, null, 0, 0, CompressType.NONE, this.filePath, null, HttpDownloadHandler);
        }
    }

    void HttpDownloadHandler(string url, string localPath, DownloadError status)
    {
        if (status == DownloadError.None)
        {
            coroutine = MyEventObject.instance.StartCoroutine(LoadLocalCoroutine());
        }
        else
        {
            HttpResourceManager.instance.OnFinish(this, null);
        }
    }

    IEnumerator LoadLocalCoroutine()
    {
		if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor)
		{
			www = new WWW("file:///" + filePath);
		}
		else
		{
			www = new WWW("file://" + filePath);
		}

        while (!www.isDone)
        {
            yield return null;
        }

        if (www.error != null)
        {
            HttpResourceManager.instance.OnFinish(this, null);
        }
        else
        {
            urlFileMap.Add(this.filePath);
            Object obj = null;
            if (resType == ResourceType.texture)
            {
                obj = www.texture;
            }
            else
            {
                obj = www.GetAudioClip(false, false, AudioType.MPEG);
            }
            HttpResourceManager.instance.OnFinish(this, obj);
        }

        Cancel();
    }
}

public class HttpResourceManager: Singleton<HttpResourceManager>
{
    Dictionary<string, System.WeakReference> texRefMap = new Dictionary<string, System.WeakReference>();
    Dictionary<string, LoadHttpResourceTask> taskMap = new Dictionary<string, LoadHttpResourceTask>();

    public void Cancel(string url, System.Action<string, Object> callBack)
    {
        if (string.IsNullOrEmpty(url))
        {
            return;
        }

        LoadHttpResourceTask task = null;
        if (taskMap.TryGetValue(url, out task))
        {
            task.callBacks.Remove(callBack);

            if (task.callBacks.Count <= 0)
            {
                this.taskMap.Remove(url);
                task.Cancel();
            }
        }
    }

    public void Load(string url, LoadHttpResourceTask.ResourceType resType, System.Action<string, Object> callBack)
    {
        if (string.IsNullOrEmpty(url))
        {
            return;
        }

        System.WeakReference reference = null;
        if (texRefMap.TryGetValue(url, out reference))
        {
            if (reference.Target != null)
            {
                callBack(url, reference.Target as Object);
                return;
            }
        }

        LoadHttpResourceTask task = null;
        if (taskMap.TryGetValue(url, out task))
        {
            task.callBacks.Add(callBack);
        }
        else
        {
            task = new LoadHttpResourceTask(url, resType);
            taskMap.Add(url, task);

            task.callBacks.Add(callBack);
            task.Load();
        }
    }

    public void OnFinish(LoadHttpResourceTask task, Object tex)
    {
        if (tex != null)
        {
			texRefMap.Remove (task.url);
            texRefMap.Add(task.url, new System.WeakReference(tex));
        }

        taskMap.Remove(task.url);

        HashSet<System.Action<string, Object>>.Enumerator e = task.callBacks.GetEnumerator();
        while (e.MoveNext())
        {
            e.Current(task.url, tex);
        }
    }
}